#pragma once
#include <coroutine>
#include <iostream>

// 协程结构体定义
template <typename T = int64_t>
class MyCoroutine
{
public:
    struct promise_type;
    using CoroHandler = std::coroutine_handle<promise_type>;

    MyCoroutine(CoroHandler h);
    ~MyCoroutine();

    bool Resume();
    bool Done();
    T GetValue();

    struct promise_type
    {
        T value = 0;

        promise_type()
        {
            std::cout << "promise_type" << std::endl;
        }

        ~promise_type()
        {
            std::cout << "~promise_type" << std::endl;
        }

        MyCoroutine get_return_object()
        {
            std::cout << "get_return_object" << std::endl;
            return MyCoroutine{CoroHandler::from_promise(*this)};
        }

        std::suspend_always initial_suspend()
        {
            std::cout << "initial_suspend" << std::endl;
            return {};
        }

        // 返回值强烈建议使用 std::suspend_always，不然容易出现崩溃，不挂起就直接析构了
        std::suspend_always final_suspend() noexcept
        {
            std::cout << "final_suspend" << std::endl;
            return {};
        }

        void unhandled_exception()
        {
            std::cout << "unhandled_exception" << std::endl;
        }

        // 当使用了 co_yield 的时候，需要实现该函数
        std::suspend_never yield_value(T v)
        {
            std::cout << "yield_value: " << v << std::endl;
            value = v;
            return {};
        }

        void return_value(T v)
        {
            std::cout << "return_value: " << v << std::endl;
            value = v;
        }

        // void return_void()
        // {
        //     std::cout << "return_void" << std::endl;
        // }
    };

private:
    CoroHandler _handle;
};